// META: title=test WebNN API relu operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long

'use strict';

// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-relu-method
// Compute the rectified linear function of the input tensor.
//
// MLOperand relu(MLOperand input);


const getReluPrecisionTolerance = (graphResources) => {
  const toleranceValueDict = {float32: 0, float16: 0};
  const expectedDataType =
      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};

const reluTests = [
  {
    'name': 'relu float32 1D constant tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'relu float32 1D tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'relu float32 2D tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'relu float32 3D tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'relu float32 4D tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 2, 2, 3], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'relu float32 5D tensor',
    'graph': {
      'inputs': {
        'reluInput': {
          'data': [
            79.04724884033203,  2.2503609657287598,  80.73938751220703,
            63.9039192199707,   77.67340850830078,   -71.0915756225586,
            -82.74703216552734, -26.81442642211914,  -99.16788482666016,
            -35.71083450317383, 18.361658096313477,  -37.36091613769531,
            -52.8386116027832,  -10.408374786376953, 60.6029167175293,
            -13.64419937133789, -76.5425033569336,   -8.132338523864746,
            51.51447296142578,  -51.63370132446289,  -64.56800079345703,
            -5.093302249908447, 15.354103088378906,  90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'relu',
        'arguments': [{'input': 'reluInput'}],
        'outputs': 'reluOutput'
      }],
      'expectedOutputs': {
        'reluOutput': {
          'data': [
            79.04724884033203,
            2.2503609657287598,
            80.73938751220703,
            63.9039192199707,
            77.67340850830078,
            0,
            0,
            0,
            0,
            0,
            18.361658096313477,
            0,
            0,
            0,
            60.6029167175293,
            0,
            0,
            0,
            51.51447296142578,
            0,
            0,
            0,
            15.354103088378906,
            90.03858947753906
          ],
          'descriptor': {'dimensions': [2, 1, 4, 1, 3], 'dataType': 'float32'}
        }
      }
    }
  }
];

if (navigator.ml) {
  reluTests.forEach((test) => {
    webnn_conformance_test(
        buildGraphAndCompute, getReluPrecisionTolerance, test);
  });
} else {
  test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}
